﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Web;
using System.Xml;
using ALinq.BBS.DataAccess;
using ALinq.BBS.Common;

namespace ALinq.BBS
{
    public class AdminSiteMapProvider : StaticSiteMapProvider
    {
        const int SETTING = 0,
                  OPTION = 1,
                  SYSTEM = 2;
        int count = 0;
        SiteMapNode root;
        bool builted = false;
        private static AdminSiteMapProvider instance;
        //static readonly ForumSection Config = Forum.ConfigSection;
        private IList<SiteMapNode> nodes;
        private SiteMapNode settingNode;
        private SiteMapNode optionNode;
        private SiteMapNode systemNode;
        private string filePath;

        public AdminSiteMapProvider()
        {
            nodes = new List<SiteMapNode>();
        }

        public static AdminSiteMapProvider Instance
        {
            get
            {
                return (AdminSiteMapProvider)SiteMap.Providers["ForumAdminSiteMap"];
            }
        }

        public override void Initialize(string name, NameValueCollection attributes)
        {
            filePath = System.Web.Hosting.HostingEnvironment.MapPath(ForumSection.Instance.VirtualPath + "Admin.sitemap");
            base.Initialize(name, attributes);
            BuildSiteMap();
        }

        public override SiteMapNode BuildSiteMap()
        {
            if (!builted)
            {
                builted = true;
                XmlDocument doc = new XmlDocument();
                doc.Load(filePath);
                XmlNode xmlRootNode = doc.DocumentElement.ChildNodes[0];
                root = CreateSiteNode(xmlRootNode);
                AddNode(root, null);

                int i = -1;
                foreach (XmlNode childNode in xmlRootNode.ChildNodes)
                {
                    if (childNode.Name != "siteMapNode")
                        continue;
                    i++;
                    SiteMapNode siteNode = CreateSiteNode(childNode);
                    AddNode(siteNode, root);
                    AppendChildren(childNode, siteNode);
                    switch (i)
                    {
                        case OPTION:
                            optionNode = siteNode;
                            break;
                        case SETTING:
                            settingNode = siteNode;
                            break;
                        case SYSTEM:
                            systemNode = siteNode;
                            break;
                    }
                }
            }
            return root;
        }

        SiteMapNode CreateSiteNode(XmlNode xmlNode)
        {
            Debug.Assert(xmlNode != null);
            SiteMapNode newSiteNode = new SiteMapNode(this, (count++).ToString());
            newSiteNode.Roles = new List<string>();

            if (xmlNode.Attributes["url"] != null)
                newSiteNode.Url = ForumSection.Instance.VirtualPath + xmlNode.Attributes["url"].Value;

            newSiteNode.Title = xmlNode.Attributes["title"].Value;
            if (xmlNode.Attributes["roles"] != null)
            {
                string[] roles = (xmlNode.Attributes["roles"].Value).Split(',');
                foreach (string role in roles)
                    newSiteNode.Roles.Add(role);
            }
            else
                newSiteNode.Roles.Add("*");
            return newSiteNode;
        }

        protected override SiteMapNode GetRootNodeCore()
        {
            return BuildSiteMap();
        }

        void AppendChildren(XmlNode xmlNode, SiteMapNode siteNode)
        {
            foreach (XmlNode item in xmlNode.ChildNodes)
            {
                if (item.Name != "siteMapNode")
                    continue;
                SiteMapNode newSiteNode = CreateSiteNode(item);
                nodes.Add(newSiteNode);
                AddNode(newSiteNode, siteNode);
                AppendChildren(item, newSiteNode);
            }
        }

        public new void AddNode(SiteMapNode node, SiteMapNode parentNode)
        {
            nodes.Add(node);
            if (parentNode != null)
                base.AddNode(node, parentNode);
            else
                base.AddNode(node);
        }

        public static SiteMapNode FindSiteMapNodeByKey(string key)
        {
            foreach (SiteMapNode node in Instance.nodes)
            {
                if (key == node.Key)
                    return node;
            }
            return null;
        }

        public override SiteMapNode FindSiteMapNodeFromKey(string key)
        {
            foreach (SiteMapNode node in nodes)
            {
                if (node.Key == key)
                    return node;
            }
            return null;
        }

        public override SiteMapNode FindSiteMapNode(string rawUrl)
        {
            foreach (SiteMapNode node in nodes)
            {
                var url1 = rawUrl.ToLower();
                var url2 = node.Url.ToLower();

                Debug.Assert(url2.EndsWith("/") == false);

                if (url1.EndsWith("/"))
                    url1 = url1.Substring(0, url1.Length - 1);


                if (url1 == url2)
                    return node;
            }
            return null;
        }

        static SiteMapNode Search(SiteMapNode node, string key)
        {
            if (node.Key == key)
                return node;

            foreach (SiteMapNode childNode in node.ChildNodes)
            {
                SiteMapNode result = Search(childNode, key);
                if (result != null)
                    return result;
            }
            return null;
        }

        /// <summary>
        /// “常规设置”菜单
        /// </summary>
        public SiteMapNode SettingNode
        {
            get
            {
                Debug.Assert(settingNode != null);
                return settingNode;
            }
        }

        /// <summary>
        /// “论坛选项”菜单
        /// </summary>
        public SiteMapNode OptionNode
        {
            get
            {
                SiteMapNode result = optionNode;
                Debug.Assert(result != null);
                return result;
            }
        }

        /// <summary>
        /// “系统设置”菜单
        /// </summary>
        public SiteMapNode SystemNode
        {
            get
            {
                Debug.Assert(systemNode != null);
                return systemNode;
            }
        }
    }
}